package com.icss.flow.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import com.google.gson.reflect.TypeToken;
import com.icss.flow.enums.FilterEnum;
import com.icss.flow.exception.CommonException;
import com.icss.flow.mapper.CommEntityMapper;
import com.icss.flow.pojo.dto.*;
import com.icss.flow.pojo.entity.Entity;
import com.icss.flow.pojo.entity.TLayoutConfig;
import com.icss.flow.pojo.entity.TMetaEntity;
import com.icss.flow.pojo.entity.TMetaField;
import com.icss.flow.enums.ModeEnum;
import com.icss.flow.enums.OpEnum;
import com.icss.flow.enums.OrderEnum;
import com.icss.flow.pojo.vo.SearchConfigVO;
import com.icss.flow.pojo.vo.TMetaFieldVO;
import com.icss.flow.service.CommEntityService;
import com.icss.flow.service.TLayoutConfigService;
import com.icss.flow.service.TMetaEntityService;
import com.icss.flow.service.TMetaFieldService;

import jakarta.annotation.Resource;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class CommEntityServiceImpl implements CommEntityService {
    @Resource
    private CommEntityMapper commEntityMapper;
    @Autowired
    private TMetaFieldService tMetaFieldService;

    @Autowired
    private TMetaEntityService tMetaEntityService;

    @Autowired
    private TLayoutConfigService layoutConfigService;


    @Override
    public TableDataInfo<?> listQuery(ListQueryDTO queryDTO) {
        List<String> fieldList = Optional.ofNullable(queryDTO.getFieldsList()).orElseThrow(() -> new CommonException("当前还未配置查询字段，请先配置查询字段！"));
        List<TMetaFieldVO> tMetaFields = tMetaFieldService.getMetaFieldList(queryDTO.getEntityCode());

        List<String> selectFields = new ArrayList<>();
        tMetaFields.forEach(tMetaField -> {
            if (fieldList.contains(tMetaField.getPhysicalName())) {
                selectFields.add(tMetaField.getPhysicalName());
            }
        });

        //搜索字段
        String searchCondition = "";
        TLayoutConfig searchLayoutConfig = layoutConfigService.getConfigByCodeAndApplyTypeAndShareTo(queryDTO.getEntityCode(), "SEARCH", "ALL");
        if (ObjectUtil.isNotEmpty(searchLayoutConfig)) {
            Gson gson = new Gson();
            List<SearchConfigVO> searchConfigVOList = gson.fromJson(searchLayoutConfig.getConfig(), new TypeToken<List<SearchConfigVO>>() {
            }.getType());
            searchCondition = buildSearchCondition(searchConfigVOList, queryDTO.getQuickFilter());
        }

        //过滤条件
        String definitionCondition = "";
        if (ObjectUtil.isNotEmpty(queryDTO.getFilter())) {
            definitionCondition = buildDefaultCondition(queryDTO.getFilter(), selectFields);
        }

        String defaultCondition = "";
        TLayoutConfig filterLayoutConfig = layoutConfigService.getConfigByCodeAndApplyTypeAndShareTo(queryDTO.getEntityCode(), "DEFAULT_FILTER", "ALL");
        if (ObjectUtil.isNotEmpty(filterLayoutConfig)) {
            Gson gson = new Gson();
            JsonElement jsonElement = JsonParser.parseString(filterLayoutConfig.getConfig());
            Filter filter = gson.fromJson(jsonElement, Filter.class);
            defaultCondition = buildDefaultCondition(filter, selectFields);
        }


        String sortStrSql = buildSortByField(queryDTO.getSortFields(), selectFields);

        TMetaEntityDTO tMetaEntityDTO = tMetaEntityService.queryById(queryDTO.getEntityCode());

        TMetaField tMetaField = tMetaFieldService.getPrimaryKeyByEntityCode(tMetaEntityDTO.getEntityCode());

        Entity entity = new Entity(tMetaEntityDTO.getPhysicalName(), selectFields);

        int offset = (queryDTO.getPageNum() - 1) * queryDTO.getPageSize();

        List<Map<String, Object>> mapList = commEntityMapper.getEntity(tMetaField.getPhysicalName(), entity, sortStrSql, searchCondition,
                defaultCondition, definitionCondition, offset, queryDTO.getPageSize());

        int count = commEntityMapper.getEntityDataCount(entity, searchCondition,
                defaultCondition, definitionCondition);
        return new TableDataInfo<>(mapList, count);
    }

    private String buildSearchCondition(List<SearchConfigVO> searchConfigVOList, String searchValue) {
        StringBuilder whereSql = new StringBuilder();
        if (CollectionUtil.isNotEmpty(searchConfigVOList)) {
            whereSql.append(" ( ");
            searchConfigVOList.forEach(searchConfig -> {
                if (searchConfig != searchConfigVOList.get(0)) {
                    whereSql.append(ModeEnum.OR.getMode()).append(" ");
                }
                whereSql.append(searchConfig.getName());
                whereSql.append(String.format(FilterEnum.LIKE.getTemplate(), buildValue(searchValue)));
            });
            whereSql.append(" ) ");
        }
        return whereSql.toString();
    }

    /**
     * 构建默认查询条件
     *
     * @param fields 指定可排序的字段列表
     * @param filter 过滤条件
     * @return 构建完成的排序字符串，格式为"字段名 排序方式,"（多个条件以逗号分隔，最后一个逗号会被移除）
     */
    public String buildDefaultCondition(Filter filter, List<String> fields) {
        StringBuilder whereSql = new StringBuilder();

        ModeEnum mode = ModeEnum.getMode(filter.getEquation());
        if (CollectionUtil.isNotEmpty(filter.getItems())) {
            whereSql.append(" ( ");
            for (FilterItem filterItem : filter.getItems()) {
                FilterEnum filterEnum = FilterEnum.getOp(filterItem.getOp());
                if (fields.contains(filterItem.getFieldName()) && Objects.nonNull(filterEnum)) {
                    whereSql.append(" ( ");
                    whereSql.append(filterItem.getFieldName());
                    whereSql.append(String.format(filterEnum.getTemplate(), buildValue(filterItem.getValue())));
                    whereSql.append(" ) ");
                    whereSql.append(mode.getMode());
                }
            }
            whereSql.append(" ) ");

        }
        int lastModeIndex = whereSql.lastIndexOf(mode.getMode());
        if (lastModeIndex != -1) {
            whereSql.delete(lastModeIndex, lastModeIndex + mode.getMode().length());
        }
        return whereSql.toString();
    }

    /**
     * 构建排序条件
     *
     * @param sortList 排序条件列表，每个条件包含字段名和排序方式
     * @param fields   指定可排序的字段列表
     * @return 构建完成的排序字符串，格式为"字段名 排序方式,"（多个条件以逗号分隔，最后一个逗号会被移除）
     */
    public String buildSortByField(List<SortFilter> sortList, List<String> fields) {
        StringBuilder orderSort = new StringBuilder();
        // 遍历排序条件列表，构建排序字符串
        if (Objects.nonNull(sortList) && !sortList.isEmpty()) {
            for (SortFilter sortFilter : sortList) {
                // 检查当前排序条件的字段是否在可排序字段列表中
                if (fields.contains(sortFilter.getFieldName())) {
                    orderSort.append(sortFilter.getFieldName());
                    orderSort.append(" ");
                    orderSort.append(OrderEnum.getOrder(sortFilter.getType()).getOrderName());
                    orderSort.append(",");
                }
            }
            // 移除排序字符串末尾多余的逗号
            if (orderSort.length() > 1) {
                orderSort.replace(orderSort.length() - 1, orderSort.length(), "");
            }
        }
        return orderSort.toString();
    }

    @Override
    public Boolean updateEntity(Integer entityCode, Integer id, Map<String, Object> param) {
        if (param.isEmpty()) {
            throw new CommonException("更新参数param不能为空");
        }
        TMetaEntityDTO tMetaEntityDTO = tMetaEntityService.queryById(entityCode);
        //校验实体以及实体字段是否存在
        checkEntityAndFieldIsExists(tMetaEntityDTO, entityCode, param);

        Entity entity = commEntityMapper.getEntityDetail(entityCode);

        TMetaField tmetaField = tMetaFieldService.getPrimaryKeyByEntityCode(entityCode);

        Map<String, Object> newParam = param.keySet().stream().filter(entity.getFields()::contains).collect(Collectors.toMap(s -> s, param::get));

        return commEntityMapper.updateEntityById(newParam, id, entity, tmetaField.getPhysicalName()) >= 1;
    }

    /**
     * 通用新增实体表数据
     *
     * @param entityCode 实体编码code
     * @param param      实体字段键值对
     * @return
     */
    @Override
    public int createEntity(Integer entityCode, Map<String, Object> param) {
        //校验实体以及实体字段是否存在
        TMetaEntityDTO tMetaEntityDTO = tMetaEntityService.queryById(entityCode);
        checkEntityAndFieldIsExists(tMetaEntityDTO, entityCode, param);

        // 创建一个新的Map用于存储转换后的值
        Map<String, Object> convertedParam = new HashMap<>();
        // 遍历原始Map，将Boolean值替换为整数
        for (Map.Entry<String, Object> entry : param.entrySet()) {
            Object value = entry.getValue();
            if (value instanceof Boolean) {
                convertedParam.put(entry.getKey(), ((Boolean) value) ? 1 : 0);
            } else {
                // 如果不是Boolean类型，则直接复制原值
                convertedParam.put(entry.getKey(), value);
            }
        }
        //进行动态添加数据
        return commEntityMapper.commonCreteEntityData(tMetaEntityDTO.getPhysicalName(), convertedParam);
    }


    private String buildValue(Object value) {
        return (Optional.ofNullable(value).orElse("") + "").replace("\"", "\\\"").replace("%", "\\%").replace("_", "\\_");
    }

    Object[] buildValue(Object[] objects) {
        Object[] newObjects = new Object[objects.length];
        for (int i = 0, objectsLength = objects.length; i < objectsLength; i++) {
            Object object = objects[i];
            newObjects[i] = buildValue(object);
        }
        return newObjects;
    }


    /***
     * 校验实体以及实体字段是否存在
     * @param entityCode
     * @param param
     * @return
     */
    private void checkEntityAndFieldIsExists(TMetaEntityDTO tMetaEntityDTO, Integer entityCode, Map<String, Object> param) {
        if (ObjectUtil.isEmpty(tMetaEntityDTO)) {
            throw new CommonException("未找到当前entityCode：" + entityCode + "的实体信息");
        }
        List<String> fieldList = tMetaFieldService.getMetaFieldList(entityCode).stream().map(TMetaFieldVO::getPhysicalName).toList();
        List<String> paramKeyList = param.keySet().stream().toList();
        paramKeyList.forEach(key -> {
            if (!fieldList.contains(key)) {
                throw new CommonException("未找到实体字段信息:" + key);
            }
        });
    }


}
